﻿using Lazy.Captcha.Core;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using YiShop.Framework.Config;
using YiShop.Framework.Constants;
using YiShop.Framework.JwtBearer;
using YiShop.System.Constants;
using YiShop.System.Enum;
using YiShop.System.Repositories;

namespace YiShop.System.Services
{
    public class SysLoginService : ITransient
    {
        private readonly ILogger<SysLoginService> _logger;
        private readonly ISqlSugarClient _client;
        private readonly ICaptcha _captcha;
        private readonly ICache _cache;
        private readonly SysLogininforService _sysLogininforService;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly SysPasswordService _passwordService;
        private readonly SysPermissionService _permissionService;
        private readonly SysUserService _userService;

        public SysLoginService(ISqlSugarClient client,
            ILogger<SysLoginService> logger,
            ICaptcha captcha,
            SysLogininforService sysLogininforService,
            ICache cache,
            IHttpContextAccessor httpContextAccessor,
            SysPasswordService passwordService,
            SysPermissionService permissionService,
            SysUserService userService)
        {
            _client = client;
            _logger = logger;
            _captcha = captcha;
            _sysLogininforService = sysLogininforService;
            _cache = cache;
            _httpContextAccessor = httpContextAccessor;
            _passwordService = passwordService;
            _permissionService = permissionService;
            _userService = userService;
        }

        /// <summary>
        /// 登录验证
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="code">验证码</param>
        /// <param name="uuid">唯一标识</param>
        /// <returns>结果</returns>
        public async Task<string> LoginAsync(LoginDto dto)
        {
            string username = dto.UserName; string password = dto.Password; string? code = dto.Code; string? uuid = dto.Uuid;
            // 验证码校验
            //ValidateCaptcha(username, code, uuid);

            // 用户验证
            var userDto = await _userService.GetDtoByUsernameAsync(username);
            CheckLoginUser(username, password, userDto);

            // 记录登录成功
            await _sysLogininforService.AddAsync(username, GlobalConstants.LOGIN_SUCCESS, LoginConstants.User_Login_Success);

            var loginUser = CreateLoginUser(userDto);
            //await RecordLoginInfoAsync(userDto.UserId ?? 0);

            loginUser.Token = Guid.NewGuid().ToString();
            loginUser.LoginTime = DateTime.Now.ToUnixTimeMilliseconds();
            loginUser.ExpireTime = loginUser.LoginTime + AppSettings.JWTSettings.ExpiredTime * 60;
            _cache.Set(CacheConstants.LOGIN_TOKEN_KEY + loginUser.Token, loginUser, AppSettings.JWTSettings.ExpiredTime);
            // 生成token
            var claims = new List<Claim>() {
                new Claim(GlobalConstants.LOGIN_USER_KEY, loginUser.Token),
                new Claim(ClaimTypes.Name, username),
                new Claim(DataConstants.USER_ID, loginUser.UserId.ToString()),
                new Claim(DataConstants.USER_DEPT_ID, loginUser.DeptId.ToString()),
                new Claim(JwtRegisteredClaimNames.Exp, DateTimeOffset.UtcNow.AddMinutes(30).ToUnixTimeSeconds().ToString()),
            };
            var token = JWTEncryption.BuildJwtToken([.. claims]);
            return token;
        }


        /// <summary>
        /// 校验验证码
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="code">验证码</param>
        /// <param name="uuid">唯一标识</param>
        private void ValidateCaptcha(string username, string? code, string? uuid)
        {
            bool captchaEnabled = true;
            if (captchaEnabled)
            {
                // 无论验证是否通过, 都删除缓存的验证码
                var isValidCaptcha = _captcha.Validate(uuid, code, true, true);
                if (!isValidCaptcha)
                {
                    Task.Factory.StartNew(async () =>
                    {
                        await _sysLogininforService.AddAsync(username, GlobalConstants.LOGIN_FAIL, LoginConstants.Captcha_Invalid);
                    });
                    _logger.LogError(LoginConstants.Captcha_Invalid);
                    throw new ServiceException(LoginConstants.Captcha_Invalid);
                }
            }
        }

        private void CheckLoginUser(string username, string password, SysUserDto user)
        {
            if (user == null)
            {
                _logger.LogInformation($"登录用户：{username} 不存在.");
                throw new ServiceException(LoginConstants.User_Passwrod_Not_Match);
            }
            else if (UserStatus.DISABLE.GetValue().Equals(user.Status))
            {
                _logger.LogInformation($"登录用户：{username} 已被停用.");
                throw new ServiceException(LoginConstants.User_Blocked);
            }

            // 密码验证
            _passwordService.Validate(username, password, user);

            /*
            var pwd = SecurityUtils.CreatePasswordHash(password, user.PasswordSalt);
            if (user.Password != pwd)
            {
                throw new ServiceException(LoginConstants.User_Passwrod_Not_Match);
            }
            */
        }

        private LoginUser CreateLoginUser(SysUserDto user)
        {
            var permissions = _permissionService.GetMenuPermission(user);
            return new LoginUser
            {
                UserId = user.UserId,
                DeptId = user.DeptId ?? 0L,
                UserName = user.UserName ?? "",
                Password = user.Password ?? "",
                User = user,
                Permissions = permissions
            };
        }

    }
}
